package com.lau.dicttranslator.serializer;

import com.lau.dicttranslator.annotation.DictField;
import com.lau.dicttranslator.enums.DictType;
import com.lau.dicttranslator.service.DictService;
import com.lau.dicttranslator.util.SpringContextHolder;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 字典字段序列化器
 * 自动为标记了@DictField注解的字段生成对应的显示名称字段
 */
@Component
@Slf4j
public class DictFieldSerializer extends JsonSerializer<Object> implements ContextualSerializer {
    
    @Autowired
    private DictService dictService;  // Spring注入的服务，用于主实例
    
    private DictField dictField;
    private String fieldName;
    private DictService contextDictService;  // 构造函数传递的服务，用于上下文实例
    
    /**
     * 默认构造函数，用于Spring实例化
     */
    public DictFieldSerializer() {
    }
    
    /**
     * 私有构造函数，用于创建上下文实例
     */
    private DictFieldSerializer(DictField dictField, String fieldName, DictService dictService) {
        this.dictField = dictField;
        this.fieldName = fieldName;
        this.contextDictService = dictService;  // 保存传递的服务实例，不覆盖Spring注入的字段
    }
    
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        // 序列化原始值
        gen.writeObject(value);
        
        // 生成字典翻译字段
        if (value != null && dictField != null) {
            String displayName = getDisplayName(value);
            if (displayName != null) {
                String nameField = fieldName + dictField.nameSuffix();
                gen.writeStringField(nameField, displayName);
            }
        }
    }
    
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        if (property != null) {
            DictField dictField = property.getAnnotation(DictField.class);
            if (dictField != null) {
                String fieldName = property.getName();
                // 传递当前Spring实例的dictService给新的上下文实例
                DictService service = getAvailableDictService();
                return new DictFieldSerializer(dictField, fieldName, service);
            }
        }
        return this;
    }
    
    /**
     * 获取显示名称
     */
    private String getDisplayName(Object value) {
        try {
            String dictKey = String.valueOf(value);
            
            // 获取可用的dictService实例
            DictService service = getAvailableDictService();
            if (service == null) {
                log.warn("无法获取DictService实例，字典翻译功能不可用");
                return null;
            }
            
            // 使用DictField注解中的缓存配置
            boolean enableCache = dictField.enableCache();
            long cacheExpire = dictField.cacheExpire();
            
            if (dictField.dictType() == DictType.DATABASE) {
                // 数据库字典翻译，使用动态缓存配置
                return service.getDictLabel(dictField.dictCode(), dictKey, enableCache, cacheExpire);
            } else if (dictField.dictType() == DictType.ENUM) {
                // 枚举字典翻译，使用动态缓存配置
                return service.getEnumLabel(dictField.dictCode(), dictKey, enableCache, cacheExpire);
            }
            
        } catch (Exception e) {
            log.error("字典翻译失败，value: {}, dictCode: {}", value, dictField.dictCode(), e);
        }
        
        return null;
    }
    
    /**
     * 获取可用的DictService实例
     * 优先使用上下文传递的实例，其次使用Spring注入的实例，最后通过SpringContextHolder获取
     */
    private DictService getAvailableDictService() {
        // 1. 优先使用上下文传递的实例
        if (contextDictService != null) {
            return contextDictService;
        }
        
        // 2. 其次使用Spring注入的实例
        if (dictService != null) {
            return dictService;
        }
        
        // 3. 最后通过SpringContextHolder获取Bean
        try {
            return SpringContextHolder.getBean(DictService.class);
        } catch (Exception e) {
            log.error("无法通过SpringContextHolder获取DictService实例: {}", e.getMessage());
            return null;
        }
    }
} 